<script setup lang="ts">
import { reactive, ref, defineExpose, defineEmits, nextTick, defineProps } from "vue"
import { addRecord } from "@/utils/record";
import dayjs from "@/utils/dayjs.ts";
import fetch from "@/api/fetch.js";
import { useRouter } from "vue-router";
import * as echarts from 'echarts';
import { 
    useWindowSize,
    useScroll,
} from '@vueuse/core'
const { height: WindowHeight, width: WindowWidth } = useWindowSize()
const min = Math.min(WindowHeight.value, WindowWidth.value)
import useAppStore from '@/pinia'
const app = useAppStore()
const router = useRouter()
const toIndex = () => {
    router.replace({
        path: '/'
    })
}

const emit = defineEmits(['again', 'back'])
const showGameResultPopup = ref(false)

const recordList = ref([])
const gameResult = reactive({})
const gameResultPopupEl = ref(null)
const pageTopEl = ref(null)
const gameResultShow = ref(false)
const recordListShow = ref(false)
const gameResultShowTotalKey = reactive({})
const showWinAnimate = ref(false)

const show = (res = {} as any, win = false) => {
    showGameResultPopup.value = true
    Object.keys(res).forEach(key => {
        gameResult[key] = res[key]
    })
    let { lastClearLineRafTime, total, hasLoss, showTotalKey = [] } = gameResult
    if (hasLoss) gameResult.win = win
    let { atkTotal = 0, clearLine = 0, clearRubbishLine = 0 } = total
    if (lastClearLineRafTime) {
        let m = gameResult.lastClearLineRafTime / 60000
        gameResult.lpm = clearLine / m
        gameResult.apm = atkTotal / m
        gameResult.apl = atkTotal / clearLine
        gameResult.adpm = (atkTotal + clearRubbishLine) / m
        gameResult.vs = gameResult.adpm * 5 / 3
        // 保留两位小数
        gameResult.lpm = Math.round(gameResult.lpm * 100) / 100
        gameResult.apm = Math.round(gameResult.apm * 100) / 100
        gameResult.adpm = Math.round(gameResult.adpm * 100) / 100
        gameResult.vs = Math.round(gameResult.vs * 100) / 100
        gameResult.apl = Math.round(gameResult.apl * 100) / 100
    }
    else {
        gameResult.lpm = 0
        gameResult.apm = 0
        gameResult.adpm = 0
        gameResult.vs = 0
        gameResult.apl = 0
    }
    // 重置
    Object.keys(gameResultShowTotalKey).map(key => {
        gameResultShowTotalKey[key] = false
    })
    showTotalKey.map((key: string) => {
        gameResultShowTotalKey[key] = true
    })
    console.log('gameResult', gameResult)
    // gameResultPopupEl.value.show()
    gameResultShow.value = true
    if (!hasLoss || hasLoss && win && gameResult.gameMode.id != 'zen' && gameResult.type == 'single') {
        // zen模式不进行保存
        // 当前只保存单人模式的记录 后续再实现保存联机对战的记录 单独获取 且不分排名 按时间排序
        showWinAnimate.value = true // 播放胜利动画
        if (app.online && app.isLogin) { // 非离线 上传记录 更新用户属性
            let userId = app.userInfo.userId
            addRecord(userId, gameResult) // 保存游戏记录
            .then(() => {
                loadList(userId)
            })

            updateUserData(userId)
        }
    }
    setTimeout(() => { 
        // 监听gameResultPopupEl滚动
        gameResultPopupEl.value?.addEventListener('scroll', (e) => {
            let scrollTop = e.target.scrollTop
            if (scrollTop <= 1) recordListShow.value = false
        })
        initEcharts()
    }, 200)
}

const loadList = (userId) => {
    let mode = gameResult.gameMode.id
    fetch('getRecord', { userId, mode })
    .then((res: any) => {
        console.log('getRecord res', res);
        let list = res || []
        let isBest = false
        if (gameResult.best == 'time') {
            isBest = list.every((i: any) => i.duration >= gameResult.rafTime)
            list.sort((a: any, b: any) => a.duration - b.duration)
        }
        if (gameResult.best == 'clearRubbishLine') {
            list = list.filter((i: any) => i.total.clearRubbishLine > 0) // 剔除未消行记录
            if (list.length) {
                isBest = list.every((i: any) => i.total.clearRubbishLine <= gameResult.total.clearRubbishLine)
                list.sort((a: any, b: any) => b.total.clearRubbishLine - a.total.clearRubbishLine)
            }
        }
        if (gameResult.best == 'vs') {
            isBest = list.every((i: any) => i.vs <= gameResult.vs)
            list.sort((a: any, b: any) => b.vs - a.vs)
        }
        list = list.map((i: any) => {
            if (i.end == gameResult.end) i.target = true
            return i
        })
        recordList.value = list
        console.log('recordList', list);
        if (isBest) {
            console.log('最佳纪录 mode: ', gameResult.gameMode.id);
        }
    })
}

const updateUserData = (userId) => {
    fetch('updateUserInfo', { userId, data: gameResult })
    .then(res => {
        app.userInfo.data = res.data
        console.log('updateUserData res', res)
    })
}

const hide = () => {
    // gameResultPopupEl.value.closePopup()
    gameResultShow.value = false
    showGameResultPopup.value = false
    recordListShow.value = false
}

const again = () => {
    app.playSound('audio5')
    hide()
    emit('again')
}
const back = () => {
    app.playSound('audio3')
    toIndex()
    setTimeout(() => { // 路由动画结束后 关闭弹窗
        hide()
    }, 500) 
}

const initEcharts = () => {
    let gameTotalEl = echarts.init(document.getElementById('gameTotal'));
    let apm = gameResult.apm > 60 ? 60 : gameResult.apm <= 0 ? 1 : gameResult.apm
    let btb = gameResult.total.btb > 6 ? 6 : gameResult.total.btb <= 0 ? 1 : gameResult.total.btb
    let tspin = gameResult.total.tspin > 6 ? 6 : gameResult.total.tspin <= 0 ? 1 : gameResult.total.tspin
    let ren = gameResult.total.maxCombo > 6 ? 6 : gameResult.total.maxCombo <= 0 ? 1 : gameResult.total.maxCombo
    let tetris = gameResult.total.tetris + gameResult.total.btbTetris > 6 ? 6 : gameResult.total.tetris + gameResult.total.btbTetris <= 0 ? 1 : gameResult.total.tetris + gameResult.total.btbTetris
    let lpm = gameResult.lpm > 48 ? 48 : gameResult.lpm <= 0 ? 1 : gameResult.lpm
    let value = [apm, btb, tspin, ren, tetris, lpm]
    let option = {
        color: ['rgba(255, 255, 255, .7)'],
        radar: {
            shape: 'circle',
            tooltip: {
                trigger: 'item'
            },
            indicator: [
                { name: 'APM', max: 60 },
                { name: 'BTB', max: 6 },
                { name: 'Tspin', max: 6 },
                { name: 'Ren', max: 6 },
                { name: 'Tetris', max: 6 },
                { name: 'LPM', max: 48 },
            ],
            axisName: {
                color: '#bbb',
                fontSize: min / 100 * 2 // 2vmin
            },
        },
        series: [
            {
                type: 'radar',
                data: [
                    {
                        value,
                        areaStyle: {
                            color: 'rgba(255, 255, 255, .5)'
                        },
                        // label: {
                        //     show: true,
                        //     formatter: function (params) {
                        //         return params.value;
                        //     }
                        // }
                    },
                ]
            }
        ]
    }
    gameTotalEl.setOption(option)
}

const showList = () => {
    recordListShow.value = !recordListShow.value
    setTimeout(() => {
        gameResultPopupEl.value.scrollTop = recordListShow.value ? pageTopEl.value.scrollHeight : 0
        if (!gameResultPopupEl.value) recordListShow.value = false
    }, 120)
}

const buttonHover = () => {
    app.playSound('audio1')
}

defineExpose({
    show,
    hide,
})

</script>

<template>

<div v-if="showGameResultPopup" :class="{show: gameResultShow, recordListShow: recordListShow}" class="gameResultPopup hasScrollbar" ref="gameResultPopupEl">
    <div ref="pageTopEl" class="pageTop flex flex-col items-center justify-evenly">
        <lottie v-if="showWinAnimate" ref="lottieRef" class="party" autoplay defaultLottie="partyFireworks" />
        <div class="title">
            <span v-if="gameResult.hasLoss">
                <span v-if="gameResult.win">PERFECT CLEAR</span>
                <span v-else>TRY AGAIN</span>
            </span>
            <span v-else>GAME FINISH</span>
        </div>
        <div class="infoBox flex items-center justify-center">
            <div class="left flex flex-col justify-evenly">
                <div v-if="gameResultShowTotalKey.apm" class="info flex items-center justify-between">
                    <div>APM</div>
                    <div>{{ gameResult.apm }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.lpm" class="info flex items-center justify-between">
                    <div>LPM</div>
                    <div>{{ gameResult.lpm }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.apl" class="info flex items-center justify-between">
                    <div>APL</div>
                    <div>{{ gameResult.apl }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.vs" class="info flex items-center justify-between">
                    <div>VS</div>
                    <div>{{ gameResult.vs }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.time" class="info flex items-center justify-between">
                    <div>TIME</div>
                    <div>{{ gameResult.timeFormat }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.mode" class="info flex items-center justify-between">
                    <div>MODE</div>
                    <div>{{ gameResult.gameMode.name }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.line" class="info flex items-center justify-between">
                    <div>CLEAR LINE</div>
                    <div>{{ gameResult.line }}</div>
                </div>
                <div v-if="gameResultShowTotalKey.targetLine" class="info flex items-center justify-between">
                    <div>TARGET LINE</div>
                    <div>{{ gameResult.targetLine }}</div>
                </div>
                <div v-if="gameResult.best == 'clearRubbishLine'" class="info flex items-center justify-between">
                    <div>CLEAR RUBBISH LINE</div>
                    <div>{{ gameResult.total.clearRubbishLine }}</div>
                </div>
            </div>
            <!-- 图表 -->
            <div class="right" id="gameTotal"></div>
        </div>
        <div class="buttonBox flex items-center justify-between">
            <div class="btn flex items-center justify-center" @mouseover="buttonHover" @click="again">AGAIN</div>
            <div class="btn btn1 flex items-center justify-center" @mouseover="buttonHover" @click="back">BACK</div>
        </div>
    </div>
    <div v-if="recordList && recordList.length" @click="showList" :class="{show: recordListShow}" class="bottomButton flex items-center justify-center">
        <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="svg bi bi-chevron-double-up" viewBox="0 0 16 16">
            <path fill-rule="evenodd" d="M7.646 2.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 3.707 2.354 9.354a.5.5 0 1 1-.708-.708l6-6z"/>
            <path fill-rule="evenodd" d="M7.646 6.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 7.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>
        </svg>
    </div>
    <div class="pageBottom">
        <div class="recordList">
            <div class="item flex items-center justify-around" v-for="(item, index) in recordList" :key="index"
            :class="{ target: item.target }"
            >
                <div class="index">{{ index + 1 }}</div>
                <div class="modeTitle">{{ gameResult.gameMode.eName }}</div>
                <div class="time">{{ dayjs(item.end).format('YYYY/MM/DD HH:mm:ss') }}</div>
                <div class="data"><span class="w">APM </span>{{ item.info.apm }}</div>
                <div class="data"><span class="w">LPM </span>{{ item.info.lpm }}</div>
                <div class="result">
                    <span v-if="gameResult.best == 'time'">{{ item.timeFormat }} <span class="w">TIME</span></span>
                    <span v-if="gameResult.best == 'clearRubbishLine'">{{ item.total.clearRubbishLine }} <span class="w">CLEAR RUBBISH LINE</span></span>
                    <span v-if="gameResult.best == 'vs'">{{ item.info.vs }} <span class="w">VS</span></span>
                </div>
                <div class="newItem" v-if="item.target">NEW</div>
            </div>
        </div>
    </div>
</div>

<!-- gameResultShow -->

<!-- 弃案 -->
<!-- <popup :keepAlive="false" ref="gameResultPopupEl">
</popup> -->

</template>

<style lang="scss" scoped>
.gameResultPopup {
    width: 100vw;
    height: 100vh;
    border-radius: 20px;
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
    opacity: 0;
    display: none;
    overflow: hidden;
    // 平滑滚动
    scroll-behavior: smooth;
    &.show {
        pointer-events: auto;
        display: block;
        animation: show forwards .3s ease-in-out;
    }
    &.recordListShow {
        overflow-y: auto;
    }
    @keyframes show {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;
        }
    }
    .pageTop {
        width: 100%;
        height: 90vh;
    }
    .pageBottom {
        width: 100%;
        min-height: 100vh;
    }
    .bottomButton {
        height: 10vh;
        width: 100%;
        transition: all .3s;
        &:hover {
            background: rgb(255, 255, 255, .05);
            transform: scale(1.1);
        }
        svg {
            width: 5vmin;
            height: 5vmin;
            color: rgb(255, 255, 255, .3);
        }
        &.show {
            svg {
                transform: rotate(180deg);
            }
        }
    }
    .party {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
    }
    .title {
        color: #fff;
        font-weight: 600;
        font-size: 8vmin;
        letter-spacing: 1.5vmin;
        text-shadow: 0.5vmin 0.5vmin 1vmin rgba(235, 90, 165, .8);
        font-family: "Floane";
        border-bottom: 1px solid rgba(204, 204, 204, .3);
        box-shadow: 0 2vmin 2vmin rgb(50,50,50,.1);
        padding: 0 16vmin 2vmin 16vmin;
    }
    .infoBox {
        width: 100%;
        .info {
            color: #ccc;
            text-shadow: 0 0 1vmin rgba(204, 204, 204, .5);
            font-size: 3vmin;
        }
        .left {
            width: max-content;
            min-width: 30vw;
            height: 100%;
            flex-shrink: 0;
        }
        .right {
            margin-left: 12vmin;
            flex-shrink: 0;
            width: 50vmin;
            height: 50vmin;
        }
    }
    .buttonBox {
        width: 80vmin;
        .btn {
            width: 35vmin;
            padding: 1.5vmin 0;
            border-radius: 1vmin;
            font-size: 4vmin;
            letter-spacing: 0.5vmin;
            color: #fff;
            background-color: #1d9099;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            text-shadow: 0.5vmin 0.5vmin 1vmin rgba(235, 90, 165, .8);
            transition: all 0.6s;
        }
        .btn:active {
            scale: 0.5;
        }
        .btn:hover {
            background: linear-gradient(315deg, rgba(2, 29, 78, 0.681) 0%, rgba(31, 215, 232, 0.873) 60%);
            color: rgb(4, 4, 38);
            opacity: 0.8;
        }
    }
    .recordList {
        width: 100%;
        height: 100%;
        overflow-y: auto;
        padding: 4vmin 16vmin;
        .item {
            width: 100%;
            height: 10vh;
            background: #7634fa;
            border-radius: 1vmin;
            margin-bottom: 4vmin;
            transition: all .2s;
            position: relative;

            .index {
                font-weight: bolder;
                font-size: 6vmin;
                text-shadow: 0.5vmin 0.5vmin 1vmin rgba(31, 215, 232, 0.573);
                font-family: "Regular";
            }

            .modeTitle {
                font-size: 3vmin;
                letter-spacing: 0.5vmin;
                text-shadow: 0.5vmin 0.5vmin 1vmin rgba(235, 90, 165, .8);
                font-family: "Floane";
                font-weight: 600;
                position: relative;
                top: 0.5vmin;
            }

            .time {
                font-size: 2.5vmin;
                font-weight: 200;
                letter-spacing: 1px;
            }

            .result {
                font-weight: bolder;
                font-size: 3.2vmin;
            }

            .data {
                font-size: 2.5vmin;
            }

            .w {
                color: #ccc;
                font-weight: 500 !important;
            }

            &:hover {
                opacity: 0.8;
                transform: scale(1.03);
            }

            &.target {
                box-shadow: 0px 0px 4vmin 0.5vmin rgba(235, 90, 165, .2);
                border: 1px solid rgba(235, 90, 165, .1);
            }

            .newItem {
                position: absolute;
                left: -3.5vmin;
                top: 50%;
                transform: translate(-100%, -50%);
                font-weight: 800;
                font-size: 3.5vmin;
                color: rgb(255, 255, 255, .8);
                text-shadow: 0.5vmin 0.5vmin 1vmin rgba(31, 215, 232, 0.273);
            }
        }
    }
}
</style>
